home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 251_01 / advexp.c < prev    next >
Text File  |  1987-10-27  |  11KB  |  542 lines

  1. /* advexp.c - expression compiler for adventure games */
  2. /*
  3.     Copyright (c) 1986, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include "advcom.h"
  8. #include "advdbs.h"
  9.  
  10. /* external routines */
  11. extern SYMBOL *sfind();
  12.  
  13. /* external variables */
  14. extern char t_token[];
  15. extern int t_value;
  16. extern int curobj;
  17. extern char *code;
  18. extern int cptr;
  19.  
  20. /* forward declarations */
  21. int do_cond(),do_and(),do_or(),do_if(),do_while(),do_progn();
  22. int do_setq(),do_return(),do_send(),do_sndsuper();
  23.  
  24. /* opcode tables */
  25. static struct { char *nt_name; int nt_code,nt_args; } *nptr,ntab[] = {
  26.     "not",        OP_NOT,        1,
  27.     "+",        OP_ADD,        2,
  28.     "-",        OP_SUB,        2,
  29.     "*",        OP_MUL,        2,
  30.     "/",        OP_DIV,        2,
  31.     "%",        OP_REM,        2,
  32.     "&",        OP_BAND,    2,
  33.     "|",        OP_BOR,        2,
  34.     "~",        OP_BNOT,    1,
  35.     "<",        OP_LT,        2,
  36.     "=",        OP_EQ,        2,
  37.     ">",        OP_GT,        2,
  38.     "getp",        OP_GETP,    2,
  39.     "setp",        OP_SETP,    3,
  40.     "class",    OP_CLASS,    1,
  41.     "match",    OP_MATCH,    2,
  42.     "print",    OP_PRINT,    1,
  43.     "print-number",    OP_PNUMBER,    1,
  44.     "print-noun",    OP_PNOUN,    1,
  45.     "terpri",    OP_TERPRI,    0,
  46.     "finish",    OP_FINISH,    0,
  47.     "chain",    OP_CHAIN,    0,
  48.     "abort",    OP_ABORT,    0,
  49.     "exit",        OP_EXIT,    0,
  50.     "save",        OP_SAVE,    0,
  51.     "restore",    OP_RESTORE,    0,
  52.     "restart",    OP_RESTART,    0,
  53.     "yes-or-no",    OP_YORN,    0,
  54.     "rand",        OP_RAND,    1,
  55.     "randomize",    OP_RNDMIZE,    0,
  56.     0
  57. };
  58. static struct { char *ft_name; int (*ft_fcn)(); } *fptr,ftab[] = {
  59.     "cond",        do_cond,
  60.     "and",        do_and,
  61.     "or",        do_or,
  62.     "if",        do_if,
  63.     "while",    do_while,
  64.     "progn",    do_progn,
  65.     "setq",        do_setq,
  66.     "return",    do_return,
  67.     "send",        do_send,
  68.     "send-super",    do_sndsuper,
  69.     0
  70. };
  71.  
  72. /* do_expr - compile a subexpression */
  73. do_expr()
  74. {
  75.     int tkn;
  76.  
  77.     switch (token()) {
  78.     case T_OPEN:
  79.     switch (tkn = token()) {
  80.     case T_IDENTIFIER:
  81.         if (in_ntab() || in_ftab())
  82.         break;
  83.     default:
  84.         stoken(tkn);
  85.         do_call();
  86.     }
  87.     break;
  88.     case T_NUMBER:
  89.     do_literal();
  90.     break;
  91.     case T_STRING:
  92.     do_literal();
  93.     break;
  94.     case T_IDENTIFIER:
  95.     do_identifier();
  96.     break;
  97.     default:
  98.     error("Expecting expression");
  99.     }
  100. }
  101.  
  102. /* in_ntab - check for a function in ntab */
  103. int in_ntab()
  104. {
  105.     for (nptr = ntab; nptr->nt_name; ++nptr)
  106.     if (strcmp(t_token,nptr->nt_name) == 0) {
  107.         do_nary(nptr->nt_code,nptr->nt_args);
  108.         return (TRUE);
  109.     }
  110.     return (FALSE);
  111. }
  112.  
  113. /* in_ftab - check for a function in ftab */
  114. int in_ftab()
  115. {
  116.     for (fptr = ftab; fptr->ft_name; ++fptr)
  117.     if (strcmp(t_token,fptr->ft_name) == 0) {
  118.         (*fptr->ft_fcn)();
  119.         return (TRUE);
  120.     }
  121.     return (FALSE);
  122. }
  123.  
  124. /* do_cond - compile the (COND ... ) expression */
  125. do_cond()
  126. {
  127.     int tkn,nxt,end;
  128.  
  129.     /* initialize the fixup chain */
  130.     end = NIL;
  131.  
  132.     /* compile each COND clause */
  133.     while ((tkn = token()) != T_CLOSE) {
  134.     require(tkn,T_OPEN);
  135.     do_expr();
  136.     putcbyte(OP_BRF);
  137.     nxt = putcword(NIL);
  138.     while ((tkn = token()) != T_CLOSE) {
  139.         stoken(tkn);
  140.         do_expr();
  141.     }
  142.     putcbyte(OP_BR);
  143.     end = putcword(end);
  144.     fixup(nxt,cptr);
  145.     }
  146.  
  147.     /* fixup references to the end of statement */
  148.     if (end)
  149.     fixup(end,cptr);
  150.     else
  151.     putcbyte(OP_NIL);
  152. }
  153.  
  154. /* do_and - compile the (AND ... ) expression */
  155. do_and()
  156. {
  157.     int tkn,end;
  158.  
  159.     /* initialize the fixup chain */
  160.     end = NIL;
  161.  
  162.     /* compile each expression */
  163.     while ((tkn = token()) != T_CLOSE) {
  164.     stoken(tkn);
  165.     do_expr();
  166.     putcbyte(OP_BRF);
  167.     end = putcword(end);
  168.     }
  169.  
  170.     /* fixup references to the end of statement */
  171.     if (end)
  172.     fixup(end,cptr);
  173.     else
  174.     putcbyte(OP_NIL);
  175. }
  176.  
  177. /* do_or - compile the (OR ... ) expression */
  178. do_or()
  179. {
  180.     int tkn,end;
  181.  
  182.     /* initialize the fixup chain */
  183.     end = NIL;
  184.  
  185.     /* compile each expression */
  186.     while ((tkn = token()) != T_CLOSE) {
  187.     stoken(tkn);
  188.     do_expr();
  189.     putcbyte(OP_BRT);
  190.     end = putcword(end);
  191.     }
  192.  
  193.     /* fixup references to the end of statement */
  194.     if (end)
  195.     fixup(end,cptr);
  196.     else
  197.     putcbyte(OP_T);
  198. }
  199.  
  200. /* do_if - compile the (IF ... ) expression */
  201. do_if()
  202. {
  203.     int tkn,nxt,end;
  204.  
  205.     /* compile the test expression */
  206.     do_expr();
  207.  
  208.     /* skip around the 'then' clause if the expression is false */
  209.     putcbyte(OP_BRF);
  210.     nxt = putcword(NIL);
  211.  
  212.     /* compile the 'then' clause */
  213.     do_expr();
  214.  
  215.     /* compile the 'else' clause */
  216.     if ((tkn = token()) != T_CLOSE) {
  217.     putcbyte(OP_BR);
  218.     end = putcword(NIL);
  219.     fixup(nxt,cptr);
  220.     stoken(tkn);
  221.     do_expr();
  222.     frequire(T_CLOSE);
  223.     nxt = end;
  224.     }
  225.  
  226.     /* handle the end of the statement */
  227.     fixup(nxt,cptr);
  228. }
  229.  
  230. /* do_while - compile the (WHILE ... ) expression */
  231. do_while()
  232. {
  233.     int tkn,nxt,end;
  234.  
  235.     /* compile the test expression */
  236.     nxt = cptr;
  237.     do_expr();
  238.  
  239.     /* skip around the 'then' clause if the expression is false */
  240.     putcbyte(OP_BRF);
  241.     end = putcword(NIL);
  242.  
  243.     /* compile the loop body */
  244.     while ((tkn = token()) != T_CLOSE) {
  245.     stoken(tkn);
  246.     do_expr();
  247.     }
  248.  
  249.     /* branch back to the start of the loop */
  250.     putcbyte(OP_BR);
  251.     putcword(nxt);
  252.  
  253.     /* handle the end of the statement */
  254.     fixup(end,cptr);
  255. }
  256.  
  257. /* do_progn - compile the (PROGN ... ) expression */
  258. do_progn()
  259. {
  260.     int tkn,n;
  261.  
  262.     /* compile each expression */
  263.     for (n = 0; (tkn = token()) != T_CLOSE; ++n) {
  264.     stoken(tkn);
  265.     do_expr();
  266.     }
  267.  
  268.     /* check for an empty statement list */
  269.     if (n == 0)
  270.     putcbyte(OP_NIL);
  271. }
  272.  
  273. /* do_setq - compile the (SETQ v x) expression */
  274. do_setq()
  275. {
  276.     char name[TKNSIZE+1];
  277.     int n;
  278.  
  279.     /* get the symbol name */
  280.     frequire(T_IDENTIFIER);
  281.     strcpy(name,t_token);
  282.  
  283.     /* compile the value expression */
  284.     do_expr();
  285.  
  286.     /* check for this being a local symbol */
  287.     if ((n = findarg(name)) >= 0)
  288.     code_setargument(n);
  289.     else if ((n = findtmp(name)) >= 0)
  290.     code_settemporary(n);
  291.     else {
  292.     n = venter(name);
  293.     code_setvariable(n);
  294.     }
  295.     frequire(T_CLOSE);
  296. }
  297.  
  298. /* do_return - handle the (RETURN [expr]) expression */
  299. do_return()
  300. {
  301.     int tkn;
  302.  
  303.     /* look for a result expression */
  304.     if ((tkn = token()) != T_CLOSE) {
  305.     stoken(tkn);
  306.     do_expr();
  307.     frequire(T_CLOSE);
  308.     }
  309.  
  310.     /* otherwise, default the result to nil */
  311.     else
  312.     putcbyte(OP_NIL);
  313.  
  314.     /* insert the return opcode */
  315.     putcbyte(OP_RETURN);
  316. }
  317.  
  318. /* do_send - handle the (SEND obj msg [expr]...) expression */
  319. do_send()
  320. {
  321.     /* start searching for the method at the object itself */
  322.     putcbyte(OP_NIL);
  323.  
  324.     /* compile the object expression */
  325.     putcbyte(OP_PUSH);
  326.     do_expr();
  327.  
  328.     /* call the general message sender */
  329.     sender();
  330. }
  331.  
  332. /* do_sndsuper - handle the (SEND-SUPER msg [expr]...) expression */
  333. do_sndsuper()
  334. {
  335.     /* start searching for the method at the current class object */
  336.     code_literal(curobj);
  337.  
  338.     /* pass the message to "self" */
  339.     putcbyte(OP_PUSH);
  340.     code_argument(findarg("self"));
  341.  
  342.     /* call the general message sender */
  343.     sender();
  344. }
  345.  
  346. /* sender - compile an expression to send a message to an object */
  347. sender()
  348. {
  349.     int tkn,n;
  350.     
  351.     /* compile the selector expression */
  352.     putcbyte(OP_PUSH);
  353.     do_expr();
  354.  
  355.     /* compile each argument expression */
  356.     for (n = 2; (tkn = token()) != T_CLOSE; ++n) {
  357.     stoken(tkn);
  358.     putcbyte(OP_PUSH);
  359.     do_expr();
  360.     }
  361.     putcbyte(OP_SEND);
  362.     putcbyte(n);
  363. }
  364.  
  365. /* do_call - compile a function call */
  366. do_call()
  367. {
  368.     int tkn,n;
  369.     
  370.     /* compile the function itself */
  371.     do_expr();
  372.  
  373.     /* compile each argument expression */
  374.     for (n = 0; (tkn = token()) != T_CLOSE; ++n) {
  375.     stoken(tkn);
  376.     putcbyte(OP_PUSH);
  377.     do_expr();
  378.     }
  379.     putcbyte(OP_CALL);
  380.     putcbyte(n);
  381. }
  382.  
  383. /* do_nary - compile nary operator expressions */
  384. do_nary(op,n)
  385.   int op,n;
  386. {
  387.     while (n--) {
  388.     do_expr();
  389.     if (n) putcbyte(OP_PUSH);
  390.     }
  391.     putcbyte(op);
  392.     frequire(T_CLOSE);
  393. }
  394.  
  395. /* do_literal - compile a literal */
  396. do_literal()
  397. {
  398.     code_literal(t_value);
  399. }
  400.  
  401. /* do_identifier - compile an identifier */
  402. do_identifier()
  403. {
  404.     SYMBOL *sym;
  405.     int n;
  406.     
  407.     if (match("t"))
  408.     putcbyte(OP_T);
  409.     else if (match("nil"))
  410.     putcbyte(OP_NIL);
  411.     else if ((n = findarg(t_token)) >= 0)
  412.     code_argument(n);
  413.